package up6.store;


import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import up6.MimeMapping;
import up6.model.FileInf;

import java.io.ByteArrayInputStream;
import java.util.Iterator;

public class MinioTool {
	
	/**
	 * API：
	 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_PutObject.html
	 * @param key 文件名称,QQ.exe
	 * @param data
	 */
	public static String putObject(String key,byte[] data) {
	
		MinioConfig cfg = new MinioConfig(); 
		OkHttpClient c = new OkHttpClient();
		//http://192.168.0.111:9001/test//123.txt
		String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key;		
	    MediaType JSON = MediaType.parse("application/octet-stream");
	    
	    RequestBody body = RequestBody.create(JSON,data);
	
	
		MinioAuthorization auth = new MinioAuthorization();
		auth.setConfig(cfg)
		.setMethod("PUT")
		.setData(data)
		.setUrl(url)
		.delHead("Content-Md5")
		.setContentType("application/octet-stream");
		
		try {
			String authstr = auth.Authorization();
			
			Request r = new Request.Builder()
					.url(url)
					.put(body)
					.header("Content-Length", String.valueOf(data.length) )
					//.header("Content-Md5", auth.dataMd5)
					.header("x-amz-date", auth.getTimeIso())
					.header("x-amz-content-sha256", auth.data_sha256_Hash)
					//.header("x-amz-content-sha256", auth.getDataHash())
					.header("Authorization", authstr)
					.build();
			Call call = c.newCall(r);
	        //同步调用,返回Response,会抛出IO异常
	        Response res = call.execute();
			//System.out.println("返回头：\n"+res.headers().toString());
			return res.header("ETag");
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		return "";
	}
	
	/**
	 * API：
	 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_GetObject.html
	 * @param key 以左斜杠开始的资源路径。/guid/QQ.exe径
	 * @param blockOffset
	 * @param blockLen
	 * @return
	 */
	public static byte[] getObject(String key,long blockOffset,long blockLen)
	{
		MinioConfig cfg = new MinioConfig(); 
		OkHttpClient c = new OkHttpClient();
		//http://192.168.0.111:9001/test//123.txt?uploads
		
		String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key;
		String range = "bytes="+String.valueOf(blockOffset)+"-"+String.valueOf(blockOffset+blockLen-1);
		
		MinioAuthorization auth = new MinioAuthorization();
		
		auth.setConfig(cfg)
		.setMethod("GET")
		.setData(("").getBytes())
		.setUrl(url)
		.delHead("content-length")
		.delHead("content-type")
		.delHead("Content-Md5")
		.setContentType("application/octet-stream; charset=utf-8");
		
		try {
			String authstr = auth.Authorization();
			
			Request r = new Request.Builder()
					.url(url)
					.get()
					.header("x-amz-date", auth.getTimeIso())
					.header("x-amz-content-sha256", auth.getDataHash())
					.header("Range", range)
					.header("Authorization", authstr)
					.build();
			Call call = c.newCall(r);
	        //同步调用,返回Response,会抛出IO异常
	        Response res = call.execute();
			//System.out.println("返回头：\n"+res.headers().toString());

            /**返回值
             * 	
	            HTTP/1.1 206 Partial Content
	            x-amz-id-2: MzRISOwyjmnupCzjI1WC06l5TTAzm7/JypPGXLh0OVFGcJaaO3KW/hRAqKOpIEEp
	            x-amz-request-id: 47622117804B3E11
	            Date: Fri, 28 Jan 2011 21:32:09 GMT
	            x-amz-meta-title: the title
	            Last-Modified: Fri, 28 Jan 2011 20:10:32 GMT
	            ETag: "b2419b1e3fd45d596ee22bdf62aaaa2f"
	            Accept-Ranges: bytes
	            Content-Range: bytes 0-9/443
	            Content-Type: text/plain
	            Content-Length: 10
	            Server: AmazonS3
	
	           [10 bytes of object data]

             */
			return res.body().bytes();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		return null;
	}
	
	/**
	 * API：
	 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_CreateMultipartUpload.html
	 * @param key guid/QQ.exe，
	 * @return
	 */
	public static String CreateMultipartUpload(String key) {
	
		//System.out.println("\n minio.创建分片上传："+key);
		MinioConfig cfg = new MinioConfig(); 
		OkHttpClient c = new OkHttpClient();
		//http://192.168.0.111:9001/test//123.txt?uploads
		String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key+"?uploads";
		String mime = MimeMapping.getType(key);
	    MediaType JSON = MediaType.parse(mime+"; charset=utf-8");
	    
	    RequestBody body = RequestBody.create(JSON,"");	
	
		MinioAuthorization auth = new MinioAuthorization();
		auth.setConfig(cfg)
		.setMethod("POST")
		.setData(("").getBytes())
		.setUrl(url)
		.delHead("Content-Md5")
		.setContentType(mime+"; charset=utf-8");
		
		try {
			String authstr = auth.Authorization();
			
			Request r = new Request.Builder()
					.url(url)
					.post(body)
					.header("Content-Length", "0" )
					//.header("Content-Md5", auth.dataMd5)
					.header("x-amz-date", auth.getTimeIso())
					.header("x-amz-content-sha256", auth.data_sha256_Hash)
					//.header("x-amz-content-sha256", auth.getDataHash())
					.header("Authorization", authstr)
					.build();
			Call call = c.newCall(r);
	        //同步调用,返回Response,会抛出IO异常
	        Response res = call.execute();
			//System.out.println("返回头：\n"+res.headers().toString());

            /**返回值
             * 	<InitiateMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
              		<Bucket>example-bucket</Bucket>
              		<Key>example-object</Key>
              		<UploadId>VXBsb2FkIElEIGZvciA2aWWpbmcncyBteS1tb3ZpZS5tMnRzIHVwbG9hZA</UploadId>
            	</InitiateMultipartUploadResult>

             */
	        if(res.code()!=200) return "";
	        
			String str = res.body().string();			
	        //System.out.println("返回值："+str);
	        SAXReader reader = new SAXReader();
	        //2.加载xml
	        Document doc = reader.read(new ByteArrayInputStream(str.getBytes("UTF-8")) );
	        Element root = doc.getRootElement();
	        Iterator iter = root.elementIterator();
	        String uploadId="";
	        while(iter.hasNext())
	        {
	        	Element e = (Element)iter.next();
	        	e.getStringValue();
	        	if(StringUtils.equals(e.getName(),"UploadId")) uploadId=e.getStringValue();
	        }
	        return uploadId;

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		return "";		
	}
	
	/**
	 * API:
	 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_UploadPart.html
	 * @param key /guid/QQ.exe
	 * @param part 基于1
	 * @param uploadID
	 * @param data
	 */
	public static String UploadPart(String key,int part,String uploadID,byte[] data) {
		//System.out.println("\n 上传片："+key +  " partNumber="+String.valueOf(part)+" UploadId="+uploadID);

		MinioConfig cfg = new MinioConfig(); 
		OkHttpClient c = new OkHttpClient();
		//http://192.168.0.111:9001/test//123.txt
		String url = cfg.endpoint+ "/" +cfg.bucket + "/"+key+"?partNumber="+String.valueOf(part)+"&uploadId="+uploadID;
		//System.out.println("查询字符串：\n"+url);
	    MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");
	    RequestBody body = RequestBody.create(JSON,data);	
	
		MinioAuthorization auth = new MinioAuthorization();
		auth.setConfig(cfg)
		.setMethod("PUT")
		.setData(data)
		.setUrl(url)
		//.delHead("x-amz-content-sha256")
		.delHead("content-md5")
		.delHead("content-type")
		.setContentType("application/octet-stream; charset=utf-8");
		
		try {
			String authstr = auth.Authorization();
			
			Request r = new Request.Builder()
					.url(url)
					.put(body)
					.header("Content-Length", String.valueOf(data.length) )
					.header("x-amz-date", auth.getTimeIso())
					.header("x-amz-content-sha256", auth.data_sha256_Hash)
					.header("Authorization", authstr)
					.build();
			Call call = c.newCall(r);
	        //同步调用,返回Response,会抛出IO异常
	        Response res = call.execute();
			//System.out.println("返回内容：\n"+res.body().string());
			//System.out.println("返回头：\n"+res.headers().toString());
			
			/**
			 * 
				HTTP/1.1 100 Continue   HTTP/1.1 200 OK
				x-amz-id-2: Zn8bf8aEFQ+kBnGPBc/JaAf9SoWM68QDPS9+SyFwkIZOHUG2BiRLZi5oXw4cOCEt
				x-amz-request-id: 5A37448A37622243
				Date: Wed, 28 May 2014 19:40:12 GMT
				ETag: "7e10e7d25dc4581d89b9285be5f384fd"
				x-amz-server-side-encryption-customer-algorithm: AES256
				x-amz-server-side-encryption-customer-key-MD5: ZjQrne1X/iTcskbY2example
			 */
			return res.header("ETag").replaceAll("\"", "");
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return "";
	}
	
	/**
	 * 参数：pathSvr,minio_id(UploadId)
	 * API:
	 * 	https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/API/API_CompleteMultipartUpload.html
	 * POST /Key+?uploadId=UploadId HTTP/1.1
		Host: Bucket.s3.amazonaws.com
		<?xml version="1.0" encoding="UTF-8"?>
		<CompleteMultipartUpload xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
		   <Part>
		      <ChecksumCRC32>string</ChecksumCRC32>
		      <ChecksumCRC32C>string</ChecksumCRC32C>
		      <ChecksumSHA1>string</ChecksumSHA1>
		      <ChecksumSHA256>string</ChecksumSHA256>
		      <ETag>string</ETag>
		      <PartNumber>integer</PartNumber>
		   </Part>
		   ...
		</CompleteMultipartUpload>

	 * @param key
	 * @param id
	 */
	public static boolean CompleteMultipartUpload(FileInf file)
	{
		//System.out.println("\n minio.合并文件：\n key="+file.S3Key()+"\n UploadId="+file.minio_id);
		MinioConfig cfg = new MinioConfig(); 
		OkHttpClient c = new OkHttpClient();
		//http://192.168.0.111:9001/test//123.txt
		String url = cfg.endpoint+ "/" +cfg.bucket + "/"+file.S3Key()+"?uploadId="+file.minio_id;
		//System.out.println("查询字符串：\n"+url);
	    MediaType JSON = MediaType.parse("application/octet-stream; charset=utf-8");	
	
	    String etags=file.etags();
	    byte[] data= etags.getBytes();
	    
	    RequestBody body = RequestBody.create(JSON,etags);
	    
		MinioAuthorization auth = new MinioAuthorization();
		auth.setConfig(cfg)
		.setMethod("POST")
		.setUrl(url)
		.setData(data)
		.delHead("Content-Md5")
		.delHead("content-type")
		.setContentType("application/octet-stream; charset=utf-8");
		
		try {
			String authstr = auth.Authorization();
			
			Request r = new Request.Builder()
					.url(url)
					.post(body)
					.header("Content-Length", String.valueOf(data.length) )
					.header("x-amz-date", auth.getTimeIso())
					.header("x-amz-content-sha256", auth.getDataHash())
					.header("Authorization", authstr)
					.build();
			Call call = c.newCall(r);
	        //同步调用,返回Response,会抛出IO异常
	        Response res = call.execute();
			//System.out.println("返回头：\n"+res.headers().toString());
	        return res.code()==200;
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}
}
